﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace ZFBActivation.Core
{
	/// <summary>
	///     字符串<see cref="string" />类型的扩展辅助操作类
	/// </summary>
	public static class StringExtensions
	{
		public static bool IsEmpty(this string value) {
			return string.IsNullOrWhiteSpace(value);
		}

		public static string ToIp(this long ipInt) {
			var sb = new StringBuilder();
			sb.Append((ipInt >> 24) & 0xFF).Append(".");
			sb.Append((ipInt >> 16) & 0xFF).Append(".");
			sb.Append((ipInt >> 8) & 0xFF).Append(".");
			sb.Append(ipInt & 0xFF);
			return sb.ToString();
		}

		public static long IpToLong(this string ip) {
			char[] separator = { '.' };
			var items = ip.Split(separator);
			return (long.Parse(items[0]) << 24)
				   | (long.Parse(items[1]) << 16)
				   | (long.Parse(items[2]) << 8)
				   | long.Parse(items[3]);
		}

		public static string HtmlToText(this string htmlStr) {
			if (string.IsNullOrEmpty(htmlStr)) return "";
			var regEx_style = "<style[^>]*?>[\\s\\S]*?<\\/style>"; //定义style的正则表达式
			var regEx_script = "<script[^>]*?>[\\s\\S]*?<\\/script>"; //定义script的正则表达式
			var regEx_html = "<[^>]+>"; //定义HTML标签的正则表达式
			htmlStr = Regex.Replace(htmlStr, regEx_style, ""); //删除css
			htmlStr = Regex.Replace(htmlStr, regEx_script, ""); //删除js
			htmlStr = Regex.Replace(htmlStr, regEx_html, ""); //删除html标记
			htmlStr = Regex.Replace(htmlStr, "\\s*|\t|\r|\n", ""); //去除tab、空格、空行
			return htmlStr.Trim();
		}

		#region 正则表达式

		#region IsMatch(是否匹配正则表达式)

		/// <summary>
		///     确定所指定的正则表达式在指定的输入字符串中是否找到了匹配项
		/// </summary>
		/// <param name="value">要搜索匹配项的字符串</param>
		/// <param name="pattern">要匹配的正则表达式模式</param>
		/// <returns>如果正则表达式找到匹配项，则为 true；否则，为 false</returns>
		public static bool IsMatch(this string value, string pattern) {
			if (value == null) return false;
			return Regex.IsMatch(value, pattern);
		}

		/// <summary>
		///     确定所指定的正则表达式在指定的输入字符串中找到匹配项
		/// </summary>
		/// <param name="value">要搜索匹配项的字符串</param>
		/// <param name="pattern">要匹配的正则表达式模式</param>
		/// <param name="options">规则</param>
		/// <returns>如果正则表达式找到匹配项，则为 true；否则，为 false</returns>
		public static bool IsMatch(this string value, string pattern, RegexOptions options) {
			if (value == null) return false;
			return Regex.IsMatch(value, pattern, options);
		}

		#endregion IsMatch(是否匹配正则表达式)

		#region GetMatch(获取匹配项)

		/// <summary>
		///     在指定的输入字符串中搜索指定的正则表达式的第一个匹配项
		/// </summary>
		/// <param name="value">要搜索匹配项的字符串</param>
		/// <param name="pattern">要匹配的正则表达式模式</param>
		/// <returns>一个对象，包含有关匹配项的信息</returns
		public static string GetMatch(this string value, string pattern) {
			if (value.IsEmpty()) return string.Empty;
			return Regex.Match(value, pattern).Value;
		}

		/// <summary>
		///     在指定的输入字符串中搜索指定的正则表达式的所有匹配项的字符串集合
		/// </summary>
		/// <param name="value">要搜索匹配项的字符串</param>
		/// <param name="pattern">要匹配的正则表达式模式</param>
		/// <returns> 一个集合，包含有关匹配项的字符串值</returns>
		public static IEnumerable<string> GetMatchingValues(this string value, string pattern) {
			if (value.IsEmpty()) return new string[] { };
			return GetMatchingValues(value, pattern, RegexOptions.None);
		}

		/// <summary>
		///     使用正则表达式来确定一个给定的正则表达式模式的所有匹配的字符串返回的枚举
		/// </summary>
		/// <param name="value">输入字符串</param>
		/// <param name="pattern">正则表达式</param>
		/// <param name="options">比较规则</param>
		/// <returns>匹配字符串的枚举</returns>
		public static IEnumerable<string> GetMatchingValues(this string value, string pattern, RegexOptions options) {
			return from Match match in GetMatches(value, pattern, options) where match.Success select match.Value;
		}

		/// <summary>
		///     使用正则表达式来确定指定的正则表达式模式的所有匹配项
		/// </summary>
		/// <param name="value">值</param>
		/// <param name="pattern">正则表达式</param>
		/// <param name="options">比较规则</param>
		/// <returns></returns>
		public static MatchCollection GetMatches(this string value, string pattern, RegexOptions options) {
			return Regex.Matches(value, pattern, options);
		}

		#endregion GetMatch(获取匹配项)

		#endregion 正则表达式

		#region 字符串判断

		#region IsNullOrEmpty(是否空字符串)

		/// <summary>
		///     确认指定的字符串是 null 还是 System.String.Empty 字符串
		/// </summary>
		/// <param name="value">值</param>
		/// <returns>结果</returns>
		public static bool IsNullOrEmpty(this string value) {
			return string.IsNullOrEmpty(value);
		}

		#endregion IsNullOrEmpty(是否空字符串)

		#region IfEmpty(检查字符串是否为空)

		/// <summary>
		///     检查字符串是否为空，若为空则返回默认值
		/// </summary>
		/// <param name="value">值</param>
		/// <param name="defaultValue">默认值</param>
		/// <returns></returns>
		public static string IfEmpty(this string value, string defaultValue) {
			return !value.IsNullOrEmpty() ? value : defaultValue;
		}

		#endregion IfEmpty(检查字符串是否为空)

		#region ExceptionIfNullOrEmpty(空字符串异常判断)

		/// <summary>
		///     如果字符串为空，抛出异常<see cref="ArgumentException" />
		/// </summary>
		/// <param name="value">值</param>
		/// <param name="message">如果值为空，则将该消息显示</param>
		/// <param name="name">传入参数名</param>
		/// <returns></returns>
		public static string ExceptionIfNullOrEmpty(this string value, string message, string name) {
			if (string.IsNullOrEmpty(value)) throw new ArgumentException(message, name);
			return value;
		}

		#endregion ExceptionIfNullOrEmpty(空字符串异常判断)

		#region IsImageFile(是否图片文件)

		/// <summary>
		///     判断指定路径是否图片文件
		/// </summary>
		/// <param name="fileName">文件名</param>
		/// <returns>结果</returns>
		public static bool IsImageFile(this string fileName) {
			if (!File.Exists(fileName)) return false;
			var filedata = File.ReadAllBytes(fileName);
			if (filedata.Length == 0) return false;
			var code = BitConverter.ToUInt16(filedata, 0);
			switch (code) {
				case 0x4D42: //bmp
				case 0xD8FF: //jpg
				case 0x4947: //gif
				case 0x5089: //png
					return true;

				default:
					return false;
			}
		}

		#endregion IsImageFile(是否图片文件)

		#region Contains(确定输入字符串是否包含指定字符串)

		/// <summary>
		///     确定输入字符串是否包含指定字符串
		/// </summary>
		/// <param name="inputValue">输入字符串</param>
		/// <param name="comparisonValue">包含字符串</param>
		/// <param name="comparisonType">区域</param>
		/// <returns></returns>
		public static bool Contains(this string inputValue, string comparisonValue, StringComparison comparisonType) {
			return inputValue.IndexOf(comparisonValue, comparisonType) != -1;
		}

		/// <summary>
		///     确定输入字符串是否包含指定字符串，且字符串不为空
		/// </summary>
		/// <param name="inputValue">输入字符串</param>
		/// <param name="comparisonValue">指定字符串</param>
		/// <returns></returns>
		public static bool ContainsEquivalenceTo(this string inputValue, string comparisonValue) {
			return BothStringsAreEmpty(inputValue, comparisonValue) ||
				   StringContainsEquivalence(inputValue, comparisonValue);
		}

		/// <summary>
		///     两个字符串是否均为空
		/// </summary>
		/// <param name="inputValue">字符串1</param>
		/// <param name="comparisonValue">字符串2</param>
		/// <returns></returns>
		private static bool BothStringsAreEmpty(string inputValue, string comparisonValue) {
			return inputValue.IsEmpty() && comparisonValue.IsEmpty();
		}

		/// <summary>
		///     确定输入字符串是否包含指定字符串，且两个字符串不为空
		/// </summary>
		/// <param name="inputValue">输入字符串</param>
		/// <param name="comparisonValue">指定字符串</param>
		/// <returns></returns>
		private static bool StringContainsEquivalence(string inputValue, string comparisonValue) {
			return !inputValue.IsEmpty() &&
				   inputValue.Contains(comparisonValue, StringComparison.InvariantCultureIgnoreCase);
		}

		/// <summary>
		///     确定字符串是否包含所提供的值
		/// </summary>
		/// <param name="value">值</param>
		/// <param name="values">提供的值</param>
		/// <returns></returns>
		public static bool ContainsAny(this string value, params string[] values) {
			return value.ContainsAny(StringComparison.CurrentCulture, values);
		}

		/// <summary>
		///     确定字符串是否包含所提供的值
		/// </summary>
		/// <param name="value">值</param>
		/// <param name="comparisonType">区域性比较</param>
		/// <param name="values">提供的值</param>
		/// <returns></returns>
		public static bool ContainsAny(this string value, StringComparison comparisonType, params string[] values) {
			return values.Any(v => value.IndexOf(v, comparisonType) > -1);
		}

		/// <summary>
		///     确定字符串是否包含所有提供的值
		/// </summary>
		/// <param name="value">值</param>
		/// <param name="values">提供的值</param>
		/// <returns></returns>
		public static bool ContainsAll(this string value, params string[] values) {
			return value.ContainsAll(StringComparison.CurrentCulture, values);
		}

		/// <summary>
		///     确定字符串是否包含所有提供的值
		/// </summary>
		/// <param name="value">值</param>
		/// <param name="comparisonType">区域性比较</param>
		/// <param name="values">提供的值</param>
		/// <returns></returns>
		public static bool ContainsAll(this string value, StringComparison comparisonType, params string[] values) {
			return values.All(v => value.IndexOf(v, comparisonType) > -1);
		}

		#endregion Contains(确定输入字符串是否包含指定字符串)

		#region IsNumeric(是否单精度浮点数)

		/// <summary>
		///     是否单精度浮点数（Float）
		/// </summary>
		/// <param name="value">值</param>
		/// <returns></returns>
		public static bool IsNumeric(this string value) {
			float output;
			return float.TryParse(value, out output);
		}

		#endregion IsNumeric(是否单精度浮点数)

		#region EquivalentTo(字符串是否全等)

		/// <summary>
		///     确定两个指定的字符串具有相同的值，参数指定区域性、大小写及比较所选用的规则
		/// </summary>
		/// <param name="value">值</param>
		/// <param name="whateverCaseString">比较字符串</param>
		/// <param name="comparison">区域性</param>
		/// <returns></returns>
		public static bool EquivalentTo(this string value, string whateverCaseString,
			StringComparison comparison = StringComparison.InvariantCultureIgnoreCase) {
			return string.Equals(value, whateverCaseString, comparison);
		}

		#endregion EquivalentTo(字符串是否全等)

		#region EqualsAny(确定字符串是否与所提供的值相等)

		/// <summary>
		///     确定字符串是否与所提供的值相等
		/// </summary>
		/// <param name="value">值</param>
		/// <param name="comparisonType">区域性比较</param>
		/// <param name="values">提供的值</param>
		/// <returns></returns>
		public static bool EqualsAny(this string value, StringComparison comparisonType, params string[] values) {
			return values.Any(v => value.Equals(v, comparisonType));
		}

		#endregion EqualsAny(确定字符串是否与所提供的值相等)

		#region IsLike(通配符比较)

		/// <summary>
		///     任何模式通配符比较
		/// </summary>
		/// <param name="value">值</param>
		/// <param name="patterns">模式</param>
		/// <returns></returns>
		public static bool IsLikeAny(this string value, params string[] patterns) {
			return patterns.Any(value.IsLike);
		}

		/// <summary>
		///     通配符比较
		/// </summary>
		/// <param name="value">值</param>
		/// <param name="pattern">模式</param>
		/// <returns></returns>
		public static bool IsLike(this string value, string pattern) {
			if (value == pattern) return true;
			if (pattern[0] == '*' && pattern.Length > 1)
				return value.Where((t, index) => value.Substring(index).IsLike(pattern.Substring(1))).Any();
			if (pattern[0] == '*')
				return true;
			if (pattern[0] == value[0]) return value.Substring(1).IsLike(pattern.Substring(1));
			return false;
		}

		#endregion IsLike(通配符比较)

		#region IsItemInEnum(检查数据是否在给定的枚举定义)

		/// <summary>
		///     检查数据是否在给定的枚举定义
		/// </summary>
		/// <typeparam name="TEnum">泛型枚举</typeparam>
		/// <param name="value">匹配的枚举</param>
		/// <returns>匿名方法条件</returns>
		public static Func<bool> IsItemInEnum<TEnum>(this string value) where TEnum : struct {
			return () => string.IsNullOrEmpty(value) || !Enum.IsDefined(typeof(TEnum), value);
		}

		#endregion IsItemInEnum(检查数据是否在给定的枚举定义)

		#region IsRangeLength(判断字符串长度是否在指定范围内)

		/// <summary>
		///     判断字符串长度是否在指定范围内
		/// </summary>
		/// <param name="source">源字符串</param>
		/// <param name="minLength">最小长度</param>
		/// <param name="maxLength">最大长度</param>
		/// <returns></returns>
		public static bool IsRangeLength(this string source, int minLength, int maxLength) {
			return source.Length >= minLength && source.Length <= maxLength;
		}

		#endregion IsRangeLength(判断字符串长度是否在指定范围内)

		#endregion 字符串判断
	}
}